Skip to content

fix: reject trailing newline in tool-name validation#3076

Open
Otis0408 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Otis0408:fix/tool-name-regex-trailing-newline
Open

fix: reject trailing newline in tool-name validation#3076
Otis0408 wants to merge 1 commit into
modelcontextprotocol:mainfrom
Otis0408:fix/tool-name-regex-trailing-newline

Conversation

@Otis0408

@Otis0408 Otis0408 commented Jul 8, 2026

Copy link
Copy Markdown

Summary

TOOL_NAME_REGEX in src/mcp/shared/tool_name_validation.py is end-anchored with $:

TOOL_NAME_REGEX = re.compile(r"^[A-Za-z0-9._-]{1,128}$")

In Python's default (non-MULTILINE) mode, $ matches at end-of-string or immediately before a single trailing \n. So a tool name ending in exactly one newline passes validation:

>>> validate_tool_name("evil_tool\n").is_valid
True          # expected: False (newline is not an allowed SEP-986 character)
>>> validate_and_warn_tool_name("evil_tool\n")
True          # no warning logged

The length guard uses len() (which counts the \n), so "a" * 127 + "\n" (length 128) also slips past both the length and the character check. Embedded and non-\n trailing control chars are already rejected correctly — only the single-trailing-newline case leaks.

Fix

Anchor the end with \Z (strict end-of-string) instead of $. No valid name is affected — re.match(r"^[A-Za-z0-9._-]{1,128}\Z", "abc") still matches; only "abc\n" now correctly fails.

Tests

Adds test_validate_tool_name_rejects_trailing_newline (parametrized over a trailing-newline name and a 128-char name whose last char is \n). Verified it fails on main (is_valid=True) and passes with the fix; the file's existing 29 tests are unchanged (no valid-name fixture ends in a newline).

TOOL_NAME_REGEX was end-anchored with $, which in Python's default mode also
matches just before a single trailing newline. So validate_tool_name("x\n")
returned is_valid=True with no warning, and a 127-char name plus "\n" (len
128) slipped past both the length and character checks. Anchor with \Z so a
trailing newline is treated as the disallowed character it is.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Re-trigger cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant